﻿using System.ComponentModel;
using System.IO;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

using TInput = System.String;
using TOutput = LoA.Shared.AnimationStructure;
using LoA.Shared.Interfaces;
using LoA.Content.Pipeline;
using LoA.Shared;
using System;

namespace LoA.Content.Pipeline {
	[ContentProcessor(DisplayName = "Animation - LoA Framework")]
	public class AnimationProcessor : ContentProcessor<TInput, TOutput> {
		private int line;
		private int row;

		/// <summary>
		/// Controls the scale of the terrain. This will be the distance between
		/// vertices in the finished terrain mesh.
		/// </summary>
		[DefaultValue(1.0f)]
		[Description("The scale of transformation.")]
		public float Scale {
			get { return scale; }
			set { scale = value; }
		}
		private float scale = 1.0f;

		/// <summary>
		/// Generates a terrain mesh from an input heightfield texture.
		/// </summary>
		public override TOutput Process(TInput input, ContentProcessorContext context) {
			TOutput result = new TOutput( );

			List<Matrix> roots = new List<Matrix>( );
			List<Matrix[ ]> transforms = new List<Matrix[ ]>( );

			line = 0;

			string[ ] sequences = input.Split('|');
			foreach (var sequence in sequences) {
				line++;
				row = 0;
				string[ ] body = sequence.Split(':');
				var matrix = Capture(body[0].Split(';'));
				//if (matrix.M11 != 1f)
				//	matrix.M11 *= Scale;
				//if (matrix.M12 != 1f)
				//	matrix.M12 *= Scale;
				//if (matrix.M13 != 1f)
				//	matrix.M13 *= Scale;
				//if (matrix.M14 != 1f)
				//	matrix.M14 *= Scale;
				//if (matrix.M21 != 1f)
				//	matrix.M21 *= Scale;
				//if (matrix.M22 != 1f)
				//	matrix.M22 *= Scale;
				//if (matrix.M23 != 1f)
				//	matrix.M23 *= Scale;
				//if (matrix.M24 != 1f)
				//	matrix.M24 *= Scale;
				//if (matrix.M31 != 1f)
				//	matrix.M31 *= Scale;
				//if (matrix.M32 != 1f)
				//	matrix.M32 *= Scale;
				//if (matrix.M33 != 1f)
				//	matrix.M33 *= Scale;
				//if (matrix.M34 != 1f)
				//	matrix.M34 *= Scale;
				//if (matrix.M41 != 1f)
				//	matrix.M41 *= Scale;
				//if (matrix.M42 != 1f)
				//	matrix.M42 *= Scale;
				//if (matrix.M43 != 1f)
				//	matrix.M43 *= Scale;
				//if (matrix.M44 != 1f)
				//	matrix.M44 *= Scale;
				roots.Add(matrix * Scale);
				List<Matrix> tranform = new List<Matrix>( );
				foreach (var trans in body[1].Split('\\')) {
					row++;
					var matrixT = Capture(trans.Split(';'));
					//if (matrixT.M11 != 1f)
					//	matrixT.M11 *= Scale;
					//if (matrixT.M12 != 1f)
					//	matrixT.M12 *= Scale;
					//if (matrixT.M13 != 1f)
					//	matrixT.M13 *= Scale;
					//if (matrixT.M14 != 1f)
					//	matrixT.M14 *= Scale;
					//if (matrixT.M21 != 1f)
					//	matrixT.M21 *= Scale;
					//if (matrixT.M22 != 1f)
					//	matrixT.M22 *= Scale;
					//if (matrixT.M23 != 1f)
					//	matrixT.M23 *= Scale;
					//if (matrixT.M24 != 1f)
					//	matrixT.M24 *= Scale;
					//if (matrixT.M31 != 1f)
					//	matrixT.M31 *= Scale;
					//if (matrixT.M32 != 1f)
					//	matrixT.M32 *= Scale;
					//if (matrixT.M33 != 1f)
					//	matrixT.M33 *= Scale;
					//if (matrixT.M34 != 1f)
					//	matrixT.M34 *= Scale;
					//if (matrixT.M41 != 1f)
					//	matrixT.M41 *= Scale;
					//if (matrixT.M42 != 1f)
					//	matrixT.M42 *= Scale;
					//if (matrixT.M43 != 1f)
					//	matrixT.M43 *= Scale;
					//if (matrixT.M44 != 1f)
					//	matrixT.M44 *= Scale;
					tranform.Add(matrixT*Scale);
				}
				transforms.Add(tranform.ToArray( ));
			}

			result.roots = roots.ToArray( );
			result.transforms = transforms.ToArray( );

			return result;
		}

		public Matrix Capture(string[ ] data) {
			Matrix result = Matrix.Identity;
			float outFloat = 0;

			if (data.Length >= 16) {
				if (float.TryParse(data[0], out outFloat))
					result.M11 = outFloat;
				if (float.TryParse(data[1], out outFloat))
					result.M12 = outFloat;
				if (float.TryParse(data[2], out outFloat))
					result.M13 = outFloat;
				if (float.TryParse(data[3], out outFloat))
					result.M14 = outFloat;
				if (float.TryParse(data[4], out outFloat))
					result.M21 = outFloat;
				if (float.TryParse(data[5], out outFloat))
					result.M22 = outFloat;
				if (float.TryParse(data[6], out outFloat))
					result.M23 = outFloat;
				if (float.TryParse(data[7], out outFloat))
					result.M24 = outFloat;
				if (float.TryParse(data[8], out outFloat))
					result.M31 = outFloat;
				if (float.TryParse(data[9], out outFloat))
					result.M32 = outFloat;
				if (float.TryParse(data[10], out outFloat))
					result.M33 = outFloat;
				if (float.TryParse(data[11], out outFloat))
					result.M34 = outFloat;
				if (float.TryParse(data[12], out outFloat))
					result.M41 = outFloat;
				if (float.TryParse(data[13], out outFloat))
					result.M42 = outFloat;
				if (float.TryParse(data[14], out outFloat))
					result.M43 = outFloat;
				if (float.TryParse(data[15], out outFloat))
					result.M44 = outFloat;
			} else {
				string input = "";
				foreach (var da in data) {
					input += da + ";";
				}
				throw new Exception("Not Matrix: line:" + line.ToString( ) + " row: " + row.ToString( ) + " input: " + input);
			}

			return result;
		}
	}
}